home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / JAS / PARSE.C < prev    next >
Text File  |  1990-03-30  |  14KB  |  702 lines

  1.  
  2. /*
  3.  * Copyright (c) 1988 by Sozobon, Limited.  Author: Joseph M Treat
  4.  *
  5.  * Permission is granted to anyone to use this software for any purpose
  6.  * on any computer system, and to redistribute it freely, with the
  7.  * following restrictions:
  8.  * 1) No charge may be made other than reasonable charges for reproduction.
  9.  * 2) Modified versions must be clearly marked as such.
  10.  * 3) The authors are not responsible for any harmful consequences
  11.  *    of using this software, even if they result from defects in it.
  12.  */
  13.  
  14. #include "jas.h"
  15.  
  16. #include "parse.h"
  17.  
  18. int line = 1;
  19. int sawerror = 0;
  20. int ignore = 0;
  21. int funny_state = -1;
  22.  
  23. jmp_buf YYljbuf;
  24. jmp_buf YYopbuf;
  25.  
  26. YYSTYPE yylval;
  27. int yywidth = 0;
  28.  
  29. int token = 0;
  30.  
  31. SYM *cursym = (SYM *) NULL;
  32.  
  33. extern SYM dot;
  34. extern long newdot;
  35.  
  36. extern EXPR Yexpr(), Xexpr(), Aexpr(), Sexpr(),
  37.         Pexpr(), Mexpr(), Uexpr(), Yfactor();
  38. extern LIST *Yname_list(), *Yexpr_list();
  39. extern OPERAND *Yoperand();
  40.  
  41. yyparse()
  42. {
  43.     token = yylex();
  44.     while ( token ) {
  45.         Yline();
  46.         dot.value = newdot;
  47.     }
  48.     return sawerror;
  49. }
  50.  
  51. Yline()
  52. {
  53.     if ( setjmp( YYljbuf ) ) {
  54.         /*
  55.          * Return here on any call to Yerror to gobble up through NL
  56.          */
  57.         while ( token && token != NL )
  58.             token = yylex();
  59.         if ( token ) {
  60.             line++;
  61.             token = yylex();
  62.         }
  63.         ignore = 0;
  64.         return;
  65.     }
  66.  
  67.     if ( Ylabel_list() )
  68.         Ystatement();
  69.  
  70.     if ( token != NL )
  71.         Yerror( "end of line expected" );
  72.     line++;
  73.     token = yylex();
  74.     ignore = 0;
  75. }
  76.  
  77. Ylabel_list()
  78. {
  79.      while ( token == NAME ) {
  80.          cursym = yylval.sym;
  81.          token = yylex();
  82.         if ( token == _EQU ) {
  83.             EXPR val;
  84.             if ( cursym->flags & (SEGMT|EQUATED) )
  85.                 Yerror( "symbol redefinition" );
  86.             token = yylex();
  87.             val = Yexpr();
  88.             if ( val.psym )
  89.                 Yerror( "illegal equated expression" );
  90.             cursym->value = val.value;
  91.             cursym->flags |= EQUATED | DEFINED;
  92.             return 0;
  93.         }
  94.          if ( token != COLON  )
  95.              Yerror( "missing ':'" );
  96.         if ( cursym->flags & (SEGMT|EQUATED) )
  97.             Yerror( "symbol redefinition" );
  98.         cursym->flags |= ( dot.flags & SEGMT ) | DEFINED;
  99.         cursym->value = dot.value;
  100.          token = yylex();
  101.      }
  102.     return 1;
  103. }
  104.  
  105. Ystatement()
  106. {
  107.     if ( token != NL ) {
  108.         Yinstruction();
  109.         cursym = (SYM *) NULL;
  110.     }
  111. }
  112.  
  113. Yinstruction()
  114. {
  115.     STMT *sp;
  116.     SYM *sym;
  117.     EXPR val;
  118.     register short size;
  119.     register LIST *lp, *xlp;
  120.     extern LIST *Yname_list();
  121.     extern LIST *Yexpr_list();
  122.  
  123.     switch ( token ) {
  124.     default:
  125.         Yerror( "syntax error" );
  126.         break;
  127.     case END:
  128.         token = yylex();
  129.         break;
  130.     case _TEXT:
  131.         chsegmt( TXT );
  132.         token = yylex();
  133.         break;
  134.     case _DATA:
  135.         chsegmt( DAT );
  136.         token = yylex();
  137.         break;
  138.     case _BSS:
  139.         chsegmt( BSS );
  140.         token = yylex();
  141.         break;
  142.     case _GLOBL:
  143.         token = yylex();
  144.         lp = Yname_list();
  145.         for ( ; lp; lp = xlp ) {
  146.             xlp = lp->next;
  147.             lp->u.sym->flags |= GLOBAL | DEFINED;
  148.             free( (char *) lp );
  149.         }
  150.         break;
  151.     case _DC:
  152.         size = yywidth;
  153.         if ( size == 0 )
  154.             Yerror( ".dc must have width specifier" );
  155.         token = yylex();
  156.         lp = Yexpr_list();
  157.  
  158.         if ( size != 8 ) {
  159.             if ( newdot & 1 ) {
  160.                 zeros( 1L );
  161.                 if ( cursym != (SYM *) NULL ) 
  162.                     cursym->value = newdot;
  163.             }
  164.         }
  165.         for ( ; lp; lp = xlp ) {
  166.             xlp = lp->next;
  167.             generate(size, GENRELOC, lp->u.val.value, lp->u.sym );
  168.             free( (char *) lp );
  169.         }
  170.         break;
  171.     case _ORG:
  172.         token = yylex();
  173.         val = Yexpr();
  174.         if ( val.psym )
  175.             Yerror( "illegal use of symbol in expression" );
  176.         if ( val.value < newdot )
  177.             Yerror( "attempt to move current location backward" );
  178.         if ( val.value > newdot ) {
  179.             if ( newdot & 1 )
  180.                 zeros( 1L );
  181.             if ( val.value > newdot )
  182.                 zeros( val.value - newdot );
  183.         }
  184.         break;
  185.     case _DS:
  186.         size = yywidth;
  187.         if ( size == 0 )
  188.             Yerror( ".ds must have width specifier" );
  189.         token = yylex();
  190.         val = Yexpr();
  191.         if ( size != 8 ) {
  192.             if ( newdot & 1 ) {
  193.                 zeros( 1L );
  194.                 if ( cursym != (SYM *) NULL ) 
  195.                     cursym->value = newdot;
  196.             }
  197.         }
  198.         if ( val.psym )
  199.             Yerror( "illegal use of symbol in expression" );
  200.         zeros( val.value * (size/8) );
  201.         break;
  202.     case _EVEN:
  203.         if ( newdot & 1 ) {
  204.             zeros( 1L );
  205.             if ( cursym != (SYM *) NULL ) 
  206.                 cursym->value = newdot;
  207.         }
  208.         token = yylex();
  209.         break;
  210.     case _COMM:
  211.          if ( (token = yylex()) != NAME  )
  212.              Yerror( "missing label" );
  213.         sym = yylval.sym;
  214.         if ( sym->flags & (SEGMT|EQUATED) )
  215.             Yerror( "symbol redefinition" );
  216.          if ( (token = yylex()) != COMMA  )
  217.              Yerror( "missing ','" );
  218.          token = yylex();
  219.          val = Yexpr();
  220.         sym->flags |= EXTERN | DEFINED;
  221.         sym->value = val.value;
  222.         break;
  223.     case INSTR:
  224.         sp = yylval.stmt;
  225.         sp->op0 = sp->op1 = (OPERAND *) NULL;
  226.         token = yylex();
  227.         if ( token != NL ) {
  228.             sp->op0 = Yoperand();
  229.             if ( token == COMMA ) {
  230.                 token = yylex();
  231.                 sp->op1 = Yoperand();
  232.             }
  233.         }
  234.         geninst( sp );
  235.         break;
  236.      }
  237.  }
  238.  
  239. LIST *
  240. Yname_list()
  241. {
  242.     register LIST *lp, *xlp;
  243.  
  244.     if ( token != NAME )
  245.         Yerror( "label expected" );
  246.     lp = xlp = ALLO(LIST);
  247.     xlp->next = (LIST *) NULL;
  248.     xlp->u.sym = yylval.sym;
  249.     token = yylex();
  250.     while ( token == COMMA ) {
  251.         if ( (token = yylex()) != NAME )
  252.             Yerror( "label expected" );
  253.         xlp->next = ALLO(LIST);
  254.         xlp = xlp->next;
  255.         xlp->next = (LIST *) NULL;
  256.         xlp->u.sym = yylval.sym;
  257.         token = yylex();
  258.     }
  259.     return lp;
  260. }
  261.  
  262. LIST *
  263. Yexpr_list()
  264. {
  265.     EXPR val;
  266.     register LIST *lp;
  267.     LIST *xlp, *slp;
  268.     extern LIST *make_slist();
  269.  
  270.     if ( token == STRING ) {
  271.         lp = make_slist( &xlp, yylval.str );
  272.         token = yylex();
  273.         free( yylval.str );
  274.     } else {
  275.         val = Yexpr();
  276.         lp = xlp = ALLO(LIST);
  277.         xlp->next = (LIST *) NULL;
  278.         xlp->u.val = val;
  279.     }
  280.     while ( token == COMMA ) {
  281.         token = yylex();
  282.         if ( token == STRING ) {
  283.             xlp->next = make_slist( &slp, yylval.str );
  284.             xlp = slp;
  285.             token = yylex();
  286.             free( yylval.str );
  287.         } else {
  288.             val = Yexpr();
  289.             xlp->next = ALLO(LIST);
  290.             xlp = xlp->next;
  291.             xlp->next = (LIST *) NULL;
  292.             xlp->u.val = val;
  293.         }
  294.     }
  295.     return lp;
  296. }
  297.  
  298. LIST *
  299. make_slist( last, string )
  300.     LIST **last;
  301.     char *string;
  302. {
  303.     char *cp;
  304.     LIST *lp, *xlp;
  305.     EXPR val;
  306.  
  307.     lp = xlp = (LIST *) NULL;
  308.  
  309.     for ( cp = string; *cp; cp++ ) {
  310.         int ch;
  311.  
  312.         if ( *cp == '\\' ) {
  313.             switch ( cp[1] ) {
  314.             case 'n': ch = '\n'; break;
  315.             case 't': ch = '\t'; break;
  316.             case 'r': ch = '\r'; break;
  317.             case 'b': ch = '\b'; break;
  318.             case '0': ch = '\0'; break;
  319.             default:  ch = cp[1]; break;
  320.             }
  321.             cp++;
  322.         } else {
  323.             ch = *cp;
  324.         }
  325.         if ( lp == (LIST *) NULL ) {
  326.             lp = xlp = ALLO(LIST);
  327.             xlp->next = (LIST *) NULL;
  328.         } else {
  329.             xlp->next = ALLO(LIST);
  330.             xlp = xlp->next;
  331.             xlp->next = (LIST *) NULL;
  332.         }
  333.         xlp->u.val.psym = (SYM *) NULL;
  334.         xlp->u.val.value = ch;
  335.     }
  336.  
  337.     *last = xlp;
  338.     return lp;
  339. }
  340.  
  341. OPERAND *
  342. Yoperand()
  343. {
  344.     register OPERAND *op;
  345.     register int reg, inx;
  346.     EXPR val;
  347.  
  348.     op = ALLO(OPERAND);
  349.     switch ( token ) {
  350.     case SREG:
  351.          op->mode = yylval.val;
  352.          token = yylex();
  353.          break;
  354.      case REG:
  355.          op->mode = yylval.val < 8 ? O_DN : O_AN;
  356.         op->reg = reg = yylval.val;
  357.          token = yylex();
  358.         if ( token == MINUS || token == DIV ) {
  359.             /*
  360.              * we have a register mask list
  361.              */
  362.             op->mode = O_REGS;
  363.             op->expr.value = 1L << reg;
  364.             while ( token == MINUS || token == DIV ) {
  365.                 int tok = token;
  366.  
  367.                 token = yylex();
  368.                 inx = yylval.val;
  369.                 if ( token != REG ) 
  370.                     Yerror("invalid register list");
  371.                 if ( tok == DIV ) {
  372.                     op->expr.value |= (1L << inx);
  373.                     reg = inx;
  374.                 } else {
  375.                     int i;
  376.  
  377.                     if ( inx < reg )
  378.                         Yerror("invalid register list");
  379.                     for ( i = reg+1; i <= inx; i++ )
  380.                         op->expr.value |= (1L << i);
  381.                 }
  382.                 token = yylex();
  383.                 if ( tok == MINUS && token == MINUS )
  384.                     Yerror("invalid register list");
  385.             }
  386.         }
  387.          break;
  388.     case LP: 
  389.         if ( (token = yylex()) != REG )
  390.             Yerror( "missing register" );
  391.         reg = yylval.val;
  392.         if ( (token = yylex()) != RP )
  393.             Yerror( "missing ')'" );
  394.         token = yylex();
  395.         if ( token == PLUS ) {
  396.             op->mode = O_POST;
  397.             op->reg = reg;
  398.             token = yylex();
  399.         } else {
  400.             op->mode = O_INDR;
  401.             op->reg = reg;
  402.         }
  403.         break;
  404.     default:
  405.         funny_state = 0;
  406.         if ( setjmp( YYopbuf ) ) {
  407.             /* 
  408.              * Yexpr() saw MINUS LP REG
  409.              */
  410.             reg = yylval.val;
  411.             if ( (token = yylex()) != RP )
  412.                 Yerror( "missing ')'" );
  413.             op->mode = O_PRE;
  414.             op->reg = reg;
  415.             token = yylex();
  416.             funny_state = -1;
  417.             break;
  418.         }
  419.         val = Yexpr();
  420.         funny_state = -1;
  421.         if ( token != LP ) {
  422.             op->mode = O_ABS;
  423.             op->expr = val;
  424.             break;
  425.         }
  426.         token = yylex();
  427.         if ( token == REG ) {
  428.             reg = yylval.val;
  429.             if ( (token = yylex()) == COMMA ) {
  430.                 if ( (token = yylex()) != REG )
  431.                     Yerror( "missing register" );
  432.                 inx = yylval.val;
  433.                 if ( yywidth == 8 )
  434.                     Yerror( "index reg can't be byte" );
  435.                 if ( yywidth == 32 )
  436.                     inx |= 0x10;
  437.                 if ( (token = yylex()) != RP )
  438.                     Yerror( "missing ')'" );
  439.                 op->mode = O_INDX;
  440.                 op->reg = reg;
  441.                 op->inx = inx;
  442.                 op->expr = val;
  443.                 token = yylex();
  444.             } else {
  445.                 if ( token != RP )
  446.                     Yerror( "missing ')'" );
  447.                 op->mode = O_DISP;
  448.                 op->reg = reg;
  449.                 op->expr = val;
  450.                 token = yylex();
  451.             }
  452.         } else if ( token == PC ) {
  453.             if ( (token = yylex()) == COMMA ) {
  454.                 if ( (token = yylex()) != REG )
  455.                     Yerror( "missing register" );
  456.                 inx = yylval.val;
  457.                 if ( yywidth == 8 )
  458.                     Yerror( "index reg can't be byte" );
  459.                 if ( yywidth == 32 )
  460.                     inx |= 0x10;
  461.                 if ( (token = yylex()) != RP )
  462.                     Yerror( "missing ')'" );
  463.                 op->mode = O_PCIX;
  464.                 op->inx = inx;
  465.                 op->expr = val;
  466.                 token = yylex();
  467.             } else {
  468.                 if ( token != RP )
  469.                     Yerror( "missing ')'" );
  470.                 op->mode = O_PCRL;
  471.                 op->expr = val;
  472.                 token = yylex();
  473.             }
  474.         } else
  475.             Yerror( "register or pc expected" );
  476.         break;
  477.     case POUND:
  478.         token = yylex();
  479.         val = Yexpr();
  480.         op->mode = O_IMM;
  481.         op->expr = val;
  482.         break;
  483.      }
  484.      return op;
  485.  }
  486.  
  487. EXPR
  488. Yexpr()
  489. {
  490.     EXPR val1, val2;
  491.  
  492.     val1 = Xexpr();
  493.     while ( token == OR ) {
  494.         funny_state = -1;
  495.         token = yylex();
  496.         val2 = Xexpr();
  497.          if ( val1.psym || val2.psym )
  498.              Yerror( "illegal use of symbol in expression" );
  499.          val1.value |= val2.value;
  500.      }
  501.      return val1;
  502. }
  503.  
  504. EXPR
  505. Xexpr()
  506. {
  507.     EXPR val1, val2;
  508.  
  509.     val1 = Aexpr();
  510.     while ( token == XOR ) {
  511.         funny_state = -1;
  512.         token = yylex();
  513.         val2 = Aexpr();
  514.          if ( val1.psym || val2.psym )
  515.              Yerror( "illegal use of symbol in expression" );
  516.          val1.value ^= val2.value;
  517.      }
  518.      return val1;
  519. }
  520.  
  521. EXPR
  522. Aexpr()
  523. {
  524.     EXPR val1, val2;
  525.  
  526.     val1 = Sexpr();
  527.     while ( token == AND ) {
  528.         funny_state = -1;
  529.         token = yylex();
  530.         val2 = Sexpr();
  531.          if ( val1.psym || val2.psym )
  532.              Yerror( "illegal use of symbol in expression" );
  533.          val1.value &= val2.value;
  534.      }
  535.      return val1;
  536. }
  537.  
  538. EXPR
  539. Sexpr()
  540. {
  541.     register int op;
  542.     EXPR val1, val2;
  543.  
  544.     val1 = Pexpr();
  545.     while ( token == LSH || token == RSH ) {
  546.         op = token;
  547.         funny_state = -1;
  548.         token = yylex();
  549.         val2 = Pexpr();
  550.          if ( val1.psym || val2.psym )
  551.              Yerror( "illegal use of symbol in expression" );
  552.          if ( op == LSH )
  553.              val1.value <<= val2.value;
  554.          else
  555.              val1.value >>= val2.value;
  556.      }
  557.      return val1;
  558. }
  559.  
  560. EXPR
  561. Pexpr()
  562. {
  563.     register int op;
  564.     EXPR val1, val2;
  565.  
  566.     val1 = Mexpr();
  567.     while ( token == PLUS || token == MINUS ) {
  568.         op = token;
  569.         funny_state = -1;
  570.         token = yylex();
  571.         val2 = Mexpr();
  572.          if ( op == PLUS ) {
  573.              if ( val1.psym && val2.psym )
  574.                  Yerror( "illegal use of symbol in expression" );
  575.             if ( val2.psym )
  576.                 val1.psym = val2.psym;
  577.             val1.value += val2.value;
  578.         } else {
  579.              if ( val2.psym )
  580.                  Yerror( "illegal use of symbol in expression" );
  581.             val1.value -= val2.value;
  582.         }
  583.      }
  584.      return val1;
  585. }
  586.  
  587. EXPR
  588. Mexpr()
  589. {
  590.     register int op;
  591.     EXPR val1, val2;
  592.     jmp_buf oldYYljbuf;
  593.  
  594.     val1 = Uexpr();
  595.     while ( token == STAR || token == DIV || token == MOD ) {
  596.         op = token;
  597.         funny_state = -1;
  598.         token = yylex();
  599.         val2 = Uexpr();
  600.          if ( val1.psym || val2.psym )
  601.              Yerror( "illegal use of symbol in expression" );
  602.          if ( op == DIV ) {
  603.              if ( val2.value == 0L ) 
  604.                  Yerror( "divison by zero" );
  605.              val1.value /= val2.value;
  606.          } else if ( op == MOD ) {
  607.              if ( val2.value == 0L ) 
  608.                  Yerror( "modulo by zero" );
  609.              val1.value %= val2.value;
  610.          } else {
  611.              val1.value *= val2.value;
  612.         }
  613.      }
  614.      return val1;
  615. }
  616.  
  617. EXPR
  618. Uexpr()
  619. {
  620.     EXPR val;
  621.  
  622.     switch ( token ) {
  623.     case MINUS:
  624.         if ( funny_state == 0 )
  625.             funny_state = 1;
  626.         else
  627.             funny_state = -1;
  628.         token = yylex();
  629.         val = Yfactor();
  630.         val.value = - val.value;
  631.          if ( val.psym )
  632.              Yerror( "illegal use of symbol in expression" );
  633.         break;
  634.     case NOT:
  635.         funny_state = -1;
  636.         token = yylex();
  637.         val = Yfactor();
  638.         if ( val.psym )
  639.              Yerror( "illegal use of symbol in expression" );
  640.         val.value = - val.value;
  641.         break;
  642.     default:
  643.         val = Yfactor();
  644.         break;
  645.     }
  646.     return val;
  647. }
  648.  
  649. EXPR
  650. Yfactor()
  651. {
  652.     EXPR val;
  653.  
  654.     switch ( token ) {
  655.     case NUMBER:
  656.         funny_state = -1;
  657.         val.psym = (SYM *) NULL;
  658.         val.value = yylval.val;
  659.         break;
  660.     case NAME:
  661.         funny_state = -1;
  662.         if ( yylval.sym->flags & EQUATED ) {
  663.             val.psym = (SYM *) NULL;
  664.             val.value = yylval.sym->value;
  665.             break;
  666.         }
  667.         val.psym = yylval.sym;
  668.         val.value = 0L;
  669.         break;
  670.     case LP:
  671.         if ( funny_state == 1 )
  672.             funny_state = 2;
  673.         else
  674.             funny_state = -1;
  675.         token = yylex();
  676.         val = Yexpr();
  677.         if ( token != RP )
  678.             Yerror( "missing ')'" );
  679.         break;
  680.     case REG:
  681.         if ( funny_state == 2 ) {
  682.             longjmp( YYopbuf, 1 );
  683.         }
  684.     default:
  685.         Yerror( "illegal expression" );
  686.     }
  687.     token = yylex();
  688.     return val;
  689. }
  690.         
  691. Yerror( s )
  692.     char *s;
  693. {
  694.     if (! ignore) {
  695.         fprintf( stderr, "jas: line %d ( %s )\n", line, s );
  696.         ignore = 1;
  697.     }
  698.     sawerror = 1;
  699.     funny_state = -1;
  700.     longjmp( YYljbuf, 1 );
  701. }
  702.